'''
@fund_detail: 获取某只基金的持仓数据
参考
    1）https://zhuanlan.zhihu.com/p/393083394，
    2）https://pypi.org/project/akshare/，
    3）https://mp.weixin.qq.com/s?__biz=MzI2NjY5NzI0NA==&mid=2247501026&idx=1&sn=378292e5435b7ef5eede36192812da3b&scene=21#wechat_redirect
'''
import akshare as ak
import pandas as pd

'''获取某只基金数据 http://fund.eastmoney.com/allfund.html'''
def get_fund(symbol,years):
    '''
     @param symbol: 基金代码,比如 易方达蓝筹精 005827，前海开源公共事业股票 005669 ； type=str
     @param years: 查询年份  type=list(str)
     @return: 基金持仓  type=dataframe
    '''
    data = pd.DataFrame()
    for yr in years:
        df_tmp = ak.fund_portfolio_hold_em(symbol=symbol, date=yr)  # akshare version: 1.3.41
        data = data.append(df_tmp)

    data['季度'] = data['季度'].apply(lambda x: x[:6])
    data['季度'] = data['季度'].str.replace('年', 'Q')
    data['占净值比例'] = pd.to_numeric(data['占净值比例'])
    return data

'''获取单只基金的十大股票名称信息'''
def fund_stock_holding(symbol,years):
    '''
     @param symbol: 基金代码,比如 易方达蓝筹精 005827，前海开源公共事业股票 005669 ； type=str
     @param years: 查询年份  type=list(str)
     @return: 单只基金的十大股票名称信息  type=dataframe
    '''

    data = pd.DataFrame()
    for yr in years:
        # df_tmp = ak.fund_em_portfolio_hold(code=code,year=yr) # akshare version: 1.0.91
        df_tmp = ak.fund_portfolio_hold_em(symbol=symbol, date=yr)  # akshare version: 1.3.41
        data = data.append(df_tmp)

    #     data['季度']=data['季度'].apply(lambda x:x[:8])
    data['季度'] = data['季度'].apply(lambda x: x[:6])
    data['季度'] = data['季度'].str.replace('年', 'Q')
    data['占净值比例'] = pd.to_numeric(data['占净值比例'])
    data = data.sort_values(['季度', '持仓市值'], ascending=[True, False])

    # 将序号按持仓市值排序，从大到小
    data1 = pd.DataFrame()
    quarter = data['季度'].unique().tolist()
    for q in quarter:
        df_tmp = data.query('季度==@q')
        df_tmp['序号'] = list(range(1, len(df_tmp) + 1))
        data1 = data1.append(df_tmp)

    df = data1.set_index(['序号', '季度']).stack().unstack([1, 2]).head(10)
    # df1.loc[:,(slice(None), ['股票名称','占净值比例'])]
    df = df.loc[:, (slice(None), '股票名称')]  # 只选取 股票名称
    df = df.droplevel(None, axis=1)
    df.columns.name = None
    df = df.reset_index()
    #     df.index.name = None
    df['基金代码'] = symbol
    cols = df.columns.tolist()
    cols = cols[:1] + cols[-1:] + cols[1:-1]  # 将基金代码列名放前面
    df = df[cols]
    return df

'''比较同一个基金同一年的不同季度的持股数变化情况'''
def fund_self_compare(symbol, years, s1, s2):
    """
    @param symbol 基金代码; type=str;
    @param years 年份列表,['yr1','yr2','……']; type=list
    @param s1 靠前的季度, 格式为 'YYYYQ1',例如: '2021Q2'; type=str
    @param s2 靠后的季度, 格式为 'YYYYQ1',例如: '2021Q2'; type=str
    注意，s1和s2的年份应在 years 里
    @return 同一个基金同一年的不同季度的持股数变化情况; type=dataframe
    """

    s1_share = s1 + '持股数'
    s2_share = s2 + '持股数'
    s1_value = s1 + '持仓市值'
    s2_value = s2 + '持仓市值'
    s1_ratio = s1 + '持仓比例'
    s2_ratio = s2 + '持仓比例'

    data = pd.DataFrame()
    for yr in years:
        # df_tmp = ak.fund_em_portfolio_hold(code="005827",year=yr) # akshare version: 1.0.91
        df_tmp = ak.fund_portfolio_hold_em(symbol=symbol, date=yr)  # akshare version: 1.3.41
        data = data.append(df_tmp)
    data['季度'] = data['季度'].apply(lambda x: x[:6])
    data['季度'] = data['季度'].str.replace('年', 'Q')
    data['占净值比例'] = pd.to_numeric(data['占净值比例'])

    df1 = data[data['季度'] == s1]
    df1 = df1[['股票代码', '股票名称', '持股数', '持仓市值', '占净值比例']]
    df1 = df1.rename(columns={'持股数': s1_share, '持仓市值': s1_value, '占净值比例': s1_ratio})
    df2 = data[data['季度'] == s2]
    df2 = df2[['股票代码', '股票名称', '持股数', '持仓市值', '占净值比例']]
    df2 = df2.rename(columns={'持股数': s2_share, '持仓市值': s2_value, '占净值比例': s2_ratio})
    print(df1)

    # 在获取了两个季度的数据后，将数据按 "股票代码" 进行拼接，在得到的 dataframe 中，可以对持股的增减情况进行判断
    df_merge = pd.merge(df1, df2, on='股票代码', how='outer')

    # Q2 和 Q4，即半年度和年度报告，是需要披露全部持仓的
    # 合并后，在dataframe 中 NaN 的数据应为 0
    if s1.endswith('Q2') or s1.endswith('Q4'):
        df_merge[s1_share] = df_merge[s1_share].fillna(0)
        df_merge[s1_value] = df_merge[s1_value].fillna(0)
        df_merge[s1_ratio] = df_merge[s1_ratio].fillna(0)

    if s2.endswith('Q2') or s2.endswith('Q4'):
        df_merge[s2_share] = df_merge[s2_share].fillna(0)
        df_merge[s2_value] = df_merge[s2_value].fillna(0)
        df_merge[s2_ratio] = df_merge[s2_ratio].fillna(0)

    df_merge['持股数变化'] = df_merge[s2_share] - df_merge[s1_share]
    df_merge = df_merge.sort_values(s2_value, ascending=False)

    df_merge['股票名称'] = df_merge['股票名称_y']
    # df_merge['股票名称'] = df_merge['股票名称'].fillna('0')
    # df_merge.loc[df_merge['股票名称']=='0','股票名称'] = df_merge.loc[df_merge['股票名称']=='0','股票名称_x']
    df_merge.loc[df_merge['股票名称'].isna(), '股票名称'] = df_merge.loc[df_merge['股票名称'].isna(), '股票名称_x']
    df_merge = df_merge[['股票代码', '股票名称', s1_share,
                         s1_value, s1_ratio,
                         s2_share, s2_value,
                         s2_ratio, '持股数变化']]
    return df_merge